package org.ethan.practice.ui;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import androidx.annotation.Nullable;
import org.ethan.practice.R;

/**
 * @ClassName: SplashView
 * @Desc:
 * @Author: ethan
 * @CreateDate: 2019/10/16 14:41
 */
public class SplashView extends View {

    private Paint mPaint;
    private float mCenterX;
    private float mCenterY;
    private float mDistance;
    private Paint mHolePaint;
    private int mBackgroundColor = Color.WHITE;
    private int[] mCircleColors;
    private float mRotateRadius = 90f;
    private float mCircleRadius = 18f;
    private ValueAnimator mValueAnimator;
    private int mRotateDuration = 1200;
    private float mCurrentRotateAngle;
    private float mCurrentHoleRadius = mCircleRadius;

    public SplashView(Context context) {
        this(context, null);
    }

    public SplashView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SplashView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mHolePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mHolePaint.setColor(mBackgroundColor);
        mHolePaint.setStyle(Paint.Style.STROKE);


        mCircleColors = context.getResources().getIntArray(R.array.splash_circle_color);
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mCenterX = w / 2f;
        mCenterY = h / 2f;
        mDistance = (float) (Math.hypot(w, h) / 2f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mSplashState == null) {
            mSplashState = new RotateState();
        }
        mSplashState.drawState(canvas);
    }

    private SplashState mSplashState;

    //规范
    public abstract class SplashState {
        abstract void drawState(Canvas canvas);
    }

    //旋转
    public class RotateState extends SplashState {

        public RotateState() {
            mValueAnimator = ValueAnimator.ofFloat(0, (float) (Math.PI * 2f));
            mValueAnimator.setRepeatCount(2);
            mValueAnimator.setDuration(mRotateDuration);
            mValueAnimator.setInterpolator(new LinearInterpolator());
            mValueAnimator.start();

            mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mCurrentRotateAngle = (float) animation.getAnimatedValue();
                    //通知view 进行onDraw
                    invalidate();
                }
            });

            mValueAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    mSplashState = new MarginState();
                }
            });
        }

        @Override
        void drawState(Canvas canvas) {
            drawBackground(canvas);
            drawCircle(canvas);
        }
    }

    //绘制背景
    public void drawBackground(Canvas canvas) {
        if (mCurrentHoleRadius > 0) {
            //绘制空心圆
            float strokeWidth = mDistance - mCurrentHoleRadius;
            float radius = strokeWidth / 2f + mCurrentHoleRadius;
            mHolePaint.setStrokeWidth(strokeWidth);
            canvas.drawCircle(mCenterX,mCenterY,radius,mHolePaint);
        } else {
            canvas.drawColor(mBackgroundColor);
        }
    }

    //绘制六个小球
    public void drawCircle(Canvas canvas) {
        float rotateAngle = (float) (2 * Math.PI / mCircleColors.length);
        for (int index = 0; index < mCircleColors.length; index++) {
            float angle = rotateAngle * index + mCurrentRotateAngle;
            float cx = (float) (mCenterX + mRotateRadius * Math.cos(angle));
            float cy = (float) (mCenterY + mRotateRadius * Math.sin(angle));
            mPaint.setColor(mCircleColors[index]);
            canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
        }
    }

    //扩散聚会
    public class MarginState extends SplashState {

        private MarginState() {
            mValueAnimator = ValueAnimator.ofFloat(mCircleRadius, mRotateRadius);
            mValueAnimator.setDuration(mRotateDuration);
            mValueAnimator.setInterpolator(new OvershootInterpolator(10f));
            mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mRotateRadius = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });

            mValueAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    mSplashState = new ExpandState();
                }
            });

            mValueAnimator.reverse();
        }

        //terminal

        @Override
        void drawState(Canvas canvas) {
            drawBackground(canvas);
            drawCircle(canvas);
        }
    }

    //水波纹
    private class ExpandState extends SplashState {

        private ExpandState() {
            mValueAnimator = ValueAnimator.ofFloat(mCircleRadius, mDistance);
            mValueAnimator.setRepeatCount(1);
            mValueAnimator.setDuration(mRotateDuration);
            mValueAnimator.setInterpolator(new LinearInterpolator());
            mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mCurrentHoleRadius = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            mValueAnimator.start();
        }

        @Override
        void drawState(Canvas canvas) {
            drawBackground(canvas);
        }
    }
}
